Timer LDD

Denne øvelse går ud på at få kendskab til kernal timers og IOCTL kald
Vi vil oprette en timer i kernal space som laver et interrupt som kalder en funktion der får en LED til at blinke med en bestemt frekvens. Vi vil så lave et IOCTL kald som kan ændre om LEDen skal blinke eller ej, og bestemme med had frekvens den skal blinke med.


Timer delen:
struct timer_list my_timer;
static void timer_rutine(unsigned long timer_cmds);

//Timer interrupt funktionens funktion
 
static void timer_rutine(unsigned long timer_cmds)
{
 
my_timer.expires = jiffies + timeout_in_sec*HZ;
add_timer(&my_timer);
 
//Dioden toggles:
 
if(LED_ON)
{
   if(LED)
   {
      gpio_set_value(gpio[6].num, 1);
      LED = 0;
   }
   else
   {
      gpio_set_value(gpio[6].num, 0);
      LED = 1;
   }
}
else
{
   gpio_set_value(gpio[6].num, 1);
}
}

// Timeren initialriseles.
init_timer(&my_timer);
 
// jiffies og HZ er predeffinerede variabler og timeout_in_sec skal bestemme hvor lang tid der gør før interrupt.
my_timer.expires = jiffies + timeout_in_sec*HZ;
 
// Her bestemmes hvilken funktion som bliver kaldt ved timer interrupt.
my_timer.function = timer_rutine;
my_timer.data = 0;
 
// Her tilføjes timeren til my_timer
add_timer(&my_timer);

IOCTL delen:
long mygpio_ioctl( struct file *filep, unsigned int cmd, unsigned long arg)
{
   int minor = MINOR(filep->f_dentry->d_inode->i_rdev);
 
   switch(cmd)
   {
      case LED_FREQ;
      timeout_in_sec = arg;
      printk(KERN_ALERT "LED frekvens er nu lavet om \n");
      break;
 
      case LED_START:
      LED_ON = 1;
      printk(KERN_ALERT "LED skulle nu blinke \n");
      break;
 
      case LED_STOP:
      LED_ON = 0;
      printk(KERN_ALERT "LED skulle nu ikke blinke \n");
      break;
 
      default:
      printk(KERN_ALERT "Ukendt iouctl-command");
   }
return 0;
}

Implementation

Implementation er nem med dette program. icotl bliver kaldt med de forskellige parameter.
#include <sys/ioctl.h>
 
main()
{
   fd = open("/dev/mygpio", O_RDWR);
   ioctl(fd, LED_START, 0);
}